/**
 * 版权所有(C)，上海勾芒信息科技，2017，所有权利保留。
 * 
 * 项目名：	cards-web
 * 文件名：	WxXmlMessage.java
 * 模块说明：	
 * 修改历史：
 * 2017年5月31日 - Debenson - 创建。
 */
package me.chanjar.weixin.message.bean;

import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.io.IOUtils;

import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamConverter;

import cn.binarywang.wx.miniapp.api.WxMaConfigEx;
import me.chanjar.weixin.common.util.crypto.WxCryptUtil;
import me.chanjar.weixin.common.util.xml.XStreamCDataConverter;
import me.chanjar.weixin.message.util.XStreamTransformer;
import me.chanjar.weixin.mp.api.WxMpConfigStorage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;

/**
 * 统一微信推送过来的消息，xml格式，支持公众号(增加卡券字段)+小程序+开放平台。
 * 
 * @author Debenson
 * @since 0.1
 */
@XStreamAlias(value = "xml", impl = WxXmlMessage.class)
public class WxXmlMessage extends WxMpXmlMessage {
  private static final long serialVersionUID = 1798941937933643040L;

  /**
   * 从xml转换
   * 
   * @param xml
   * @return
   */
  public static WxXmlMessage fromXml(String xml) {
    return XStreamTransformer.fromXml(WxXmlMessage.class, xml);
  }

  /**
   * 从xml字符流转换
   * 
   * @param is
   * @return
   */
  public static WxXmlMessage fromXml(InputStream is) {
    return XStreamTransformer.fromXml(WxXmlMessage.class, is);
  }

  /**
   * 从加密字符串流转换
   * 
   * @param is
   * @param mpConfig
   * @param timestamp
   * @param nonce
   * @param msgSignature
   * @return
   */
  public static WxXmlMessage fromEncryptedXml(InputStream is, WxMpConfigStorage mpConfig,
      String timestamp, String nonce, String msgSignature) {
    try {
      return fromEncryptedXml(IOUtils.toString(is, "UTF-8"), mpConfig, timestamp, nonce,
          msgSignature);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * 从加密字符串转换
   *
   * @param encryptedXml
   * @param mpConfig
   * @param timestamp
   * @param nonce
   * @param msgSignature
   */
  public static WxXmlMessage fromEncryptedXml(String encryptedXml, WxMpConfigStorage mpConfig,
      String timestamp, String nonce, String msgSignature) {
    return fromEncryptedXml(encryptedXml, mpConfig.getToken(), mpConfig.getAesKey(),
        mpConfig.getAppId(), timestamp, nonce, msgSignature);
  }

  /**
   * 从加密字符串流转换
   * 
   * @param is
   * @param wxMpConfigStorage
   * @param timestamp
   * @param nonce
   * @param msgSignature
   * @return
   */
  public static WxXmlMessage fromEncryptedXml(InputStream is, WxMaConfigEx appConfig,
      String timestamp, String nonce, String msgSignature) {
    try {
      return fromEncryptedXml(IOUtils.toString(is, "UTF-8"), appConfig.getToken(),
          appConfig.getAesKey(), appConfig.getAppid(), timestamp, nonce, msgSignature);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * 从加密字符串转换
   * 
   * @param encryptedXml
   * @param token
   * @param aesKey
   * @param appId
   * @param timestamp
   * @param nonce
   * @param msgSignature
   * @return
   */
  public static WxXmlMessage fromEncryptedXml(String encryptedXml, String token, String aesKey,
      String appId, String timestamp, String nonce, String msgSignature) {
    WxCryptUtil cryptUtil = new WxCryptUtil(token, aesKey, appId);
    String plainText = cryptUtil.decrypt(msgSignature, timestamp, nonce, encryptedXml);
    return fromXml(plainText);
  }

  ///////////////////////////////////////
  // 卡券相关事件推送
  ///////////////////////////////////////
  @XStreamAlias("RefuseReason")
  @XStreamConverter(value = XStreamCDataConverter.class)
  private String refuseReason;

  @XStreamAlias("IsRecommendByFriend")
  private Integer isRecommendByFriend;

  ///////////////////////////////////////
  // 小程序相关事件推送
  ///////////////////////////////////////
  @XStreamAlias("SessionFrom")
  @XStreamConverter(value = XStreamCDataConverter.class)
  private String sessionFrom;

  ///////////////////////////////////////
  // 第三方平台相关事件推送
  ///////////////////////////////////////

  /** 第三方平台appid */
  @XStreamAlias("AppId")
  @XStreamConverter(value = XStreamCDataConverter.class)
  private String appId;

  /** component_verify_ticket, */
  @XStreamAlias("InfoType")
  @XStreamConverter(value = XStreamCDataConverter.class)
  private String infoType;

  /** Ticket内容 */
  @XStreamAlias("ComponentVerifyTicket")
  @XStreamConverter(value = XStreamCDataConverter.class)
  private String componentVerifyTicket;

  /** 公众号或小程序appid */
  @XStreamAlias("AuthorizerAppid")
  @XStreamConverter(value = XStreamCDataConverter.class)
  private String authorizerAppid;

  /** 授权码，可用于换取公众号的接口调用凭据，详细见上面的说明 */
  @XStreamAlias("AuthorizationCode")
  @XStreamConverter(value = XStreamCDataConverter.class)
  private String authorizationCode;

  /** 授权码过期时间 */
  @XStreamAlias("AuthorizationCodeExpiredTime")
  private Long authorizationCodeExpiredTime;

  /** 小程序代码审核成功时的时间（整形），时间戳 */
  @XStreamAlias("SuccTime")
  private Long codeAuditSuccTime;

  /** 授权码，可用于换取公众号的接口调用凭据，详细见上面的说明 */
  @XStreamAlias("Reason")
  @XStreamConverter(value = XStreamCDataConverter.class)
  private String codeAuditFailedReason;

  public String getAppId() {
    return appId;
  }

  public void setAppId(String appId) {
    this.appId = appId;
  }

  /**
   * <pre>
   * 当接受用户消息时，可能会获得以下值：
   * {@link com.gomore.wechat.mp.config.WxConsts#INFO_TYPE_AUTHORIZED}
   * {@link com.gomore.wechat.mp.config.WxConsts#INFO_TYPE_UNAUTHORIZED}
   * {@link com.gomore.wechat.mp.config.WxConsts#INFO_TYPE_UPDATEAUTHORIZED}
   * {@link com.gomore.wechat.mp.config.WxConsts#INFO_TYPE_COMPONENT_VERIFY_TICKET}
   * </pre>
   */
  public String getInfoType() {
    return infoType;
  }

  public void setInfoType(String infoType) {
    this.infoType = infoType;
  }

  public String getComponentVerifyTicket() {
    return componentVerifyTicket;
  }

  public void setComponentVerifyTicket(String componentVerifyTicket) {
    this.componentVerifyTicket = componentVerifyTicket;
  }

  /** 卡券审核不通过的原因 */
  public String getRefuseReason() {
    return refuseReason;
  }

  public void setRefuseReason(String refuseReason) {
    this.refuseReason = refuseReason;
  }

  public Integer getIsRecommendByFriend() {
    return isRecommendByFriend;
  }

  public void setIsRecommendByFriend(Integer isRecommendByFriend) {
    this.isRecommendByFriend = isRecommendByFriend;
  }

  public String getSessionFrom() {
    return sessionFrom;
  }

  public void setSessionFrom(String sessionFrom) {
    this.sessionFrom = sessionFrom;
  }

  public String getAuthorizerAppid() {
    return authorizerAppid;
  }

  public void setAuthorizerAppid(String authorizerAppid) {
    this.authorizerAppid = authorizerAppid;
  }

  public String getAuthorizationCode() {
    return authorizationCode;
  }

  public void setAuthorizationCode(String authorizationCode) {
    this.authorizationCode = authorizationCode;
  }

  public Long getAuthorizationCodeExpiredTime() {
    return authorizationCodeExpiredTime;
  }

  public void setAuthorizationCodeExpiredTime(Long authorizationCodeExpiredTime) {
    this.authorizationCodeExpiredTime = authorizationCodeExpiredTime;
  }

  public Long getCodeAuditSuccTime() {
    return codeAuditSuccTime;
  }

  public void setCodeAuditSuccTime(Long codeAuditSuccTime) {
    this.codeAuditSuccTime = codeAuditSuccTime;
  }

  public String getCodeAuditFailedReason() {
    return codeAuditFailedReason;
  }

  public void setCodeAuditFailedReason(String codeAuditFailedReason) {
    this.codeAuditFailedReason = codeAuditFailedReason;
  }

}
